from fastapi import APIRouter, HTTPException, status, Depends
from fastapi.security import OAuth2PasswordBearer
from datetime import datetime, timedelta
from typing import Optional
from jose.exceptions import JWTError
from jose import jwt
import bcrypt
from pydantic import BaseModel

from config import jwt_config
from tables.user import Users


router = APIRouter(
    prefix="/rag/auth",
    tags=["auth"],
    responses={404: {"description": "Not found"}}
)
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")


def get_password_hash(password: str) -> str:
    # 生成盐
    salt = bcrypt.gensalt()
    # 生成哈希值
    hashed_password = bcrypt.hashpw(password.encode('utf-8'), salt)
    return hashed_password.decode('utf-8')

def verify_password(password: str, hashed_password: str) -> bool:
    # 验证密码
    return bcrypt.checkpw(password.encode('utf-8'), hashed_password.encode('utf-8'))


def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
    """创建访问令牌"""
    to_encode = data.copy()
    expire = datetime.utcnow() + (expires_delta or timedelta(minutes=300))
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, jwt_config["secret_key"], algorithm=jwt_config["algorithm"])
    return encoded_jwt


async def verify_token(token: str = Depends(oauth2_scheme)):
    """验证token"""
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="无效的认证凭据",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, jwt_config["secret_key"], algorithms=[jwt_config["algorithm"]])
        user_id = payload.get("id")
        if not user_id:
            raise credentials_exception
        return Users.get_user_by_id(user_id)
    except JWTError:
        raise credentials_exception


class LoginModel(BaseModel):
    username: str
    password: str

@router.post("/login", summary="登录")
async def login(form_data: LoginModel):
    """登录获取token"""
    try:
        user = Users.get_user_by_name(form_data.username)
        if not user or not verify_password(form_data.password, user.password):
            raise Exception("用户名或密码错误")

        access_token_expires = timedelta(minutes=jwt_config["expire_minutes"])
        access_token = create_access_token(
            data={"id": user.id},
            expires_delta=access_token_expires
        )

        return {
            "code": 200,
            "access_token": access_token,
            "message": "获取成功，token类型为bearer"
        }
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail=f"登录失败: {str(e)}"
        )


class RegisterModel(BaseModel):
    username: str
    password: str
    email: str = ""


@router.post("/register", summary="注册")
async def register(form_data: RegisterModel):
    """注册"""
    try:
        user = Users.get_user_by_name(form_data.username)
        if user:
            raise Exception("用户名已存在")
        user = Users.insert_new_user(
            username=form_data.username,
            password=get_password_hash(form_data.password)
        )
        access_token_expires = timedelta(minutes=jwt_config["expire_minutes"])
        access_token = create_access_token(
            data={"id": user.id},
            expires_delta=access_token_expires
        )
        return {
            "code": 200,
            "access_token": access_token,
            "message": "注册成功，token类型为bearer"
        }
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"注册失败: {str(e)}"
        )